/**
 * @author Hemant
 * GenerateMasterCommand.java
 * This class is used to register masters and its properties of a web page that has to be regsitered.
 */


/*
*Released on 28th June 2008.
*Any violations can be reported at paritosh@wikiocean.net
*What is treated as violations can be found at www.wikiocean.net/ppl1-voilations*
******************************************************************************
* The contents of this file are subject to POOL Public License 1.0 and later.
* POOL Public License is based on Affero GPL v3 and additional conditions.
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the Affero GPL v3 License at http://www.gnu.org/licenses/agpl.html
* You may obtain a copy of the POOL Public License 1.0 or later at www.wikiocean.net/license/ppl.html
* Software distributed under POOL Public License 1.0 is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Initial Developer of the Original Code is Paritosh Pungaliya (C) 2008. All Rights Reserved.
******************************************************************************
* Objective of the additional terms (license)
* 1) Is to extend the software freedom to freedom to work.
* 2) To ensure that knowledge is free from monopoly of agencies.
* 3) To avoid a situation where big corporate or investor can buy out free software groups and companies and then start milking the communities built around it.
* (this trend can be seen how the freedom is curtailed in companies that get Venture Capital funding.)
******************************************************************************
*/

package   guiregistration;

import java.util.*;

import guifilegenerator.FileObjectsfinder;
import dbmanager.*;
import utility.*;

 
public class GenerateMasterCommand
{
	// This hash contains objects as keys and its property list as value.
	LinkedHashMap<Object,LinkedList<Object>> new_hash,old_hash;
	LinkedHashMap<Object,LinkedList<Object>> BackUp_HtmlTags;
	LinkedList<Object> NonSequentialObjects = new LinkedList<Object>();
	LinkedList<Object> SequentialObjects = new LinkedList<Object>();
    GetIdName get;
    MasterPLOperations masterpl;
    String username = "systemuser",password = "system",report;
    public String old_parent,new_parent,property,ref;
	String start_object,header="";
    /**
     * Parametarized Constructor for accepting two HashMaps. 
     * @param Tag_parent HashMap with parent-child relations
     * @param HtmlTags HashMap with Objects and its proerties
     */
    public GenerateMasterCommand(String start_obj, LinkedHashMap<Object, LinkedList<Object>> hash) 
    {
	    try
	    {
	    	get = new GetIdName();
	    	this.new_hash = hash;
	    	this.start_object = start_obj;
	    	//this.masterpl = new MasterPLOperations(uname,pass,this.db);
	        	        
	        SequentialObjects.add("report");
	        SequentialObjects.add("storage");
	        SequentialObjects.add("displaytext");
	        NonSequentialObjects.add("text");
	        NonSequentialObjects.add("type");
	        NonSequentialObjects.add("path");
	        //UserDefinedObjects.add("");	        
	    }
        catch (Exception e) 
        {
        	e.printStackTrace();
		}
    }
    
    public void setHeader(String header)
    {    	
    	this.header = header;
    }
    public void setUsername(String username)
    {
        this.username = username;
    }
   
    public void setPassword(String password)
    {
        this.password = password;
    }
     /*
     * This method  registers objects and its properties one by one.
     */
    public void register()
    {
		try
		{
			this.masterpl = new MasterPLOperations(username,password);			
			LinkedList<Object> list = new_hash.get(start_object);
			
			//finding actual Html Tag.
			String HtmlTagName = start_object.split("_")[0];                                     
			System.out.println("Object "+start_object+"   type    "+HtmlTagName);
			
			masterpl.setMaster(start_object);				
			
			if(!this.header.trim().equalsIgnoreCase(""))
			{
				//insert "tag"/property
    			MasterPLOperations mp = new MasterPLOperations(username,password);
				mp.setMaster("header");
				mp.setNewProperty("header", "type", "property", "1");
				mp.insertMaster("header");
				
				masterpl.setNewProperty(start_object, "header", this.header, "1");
			}
			
			for(int i=0;i<list.size();i++)
    		{
				System.out.println(list.get(i).toString());
				String propArr[] = list.get(i).toString().split("\t");
    			String property = propArr[0];
    			String value = propArr[1];
    			String ref = propArr[2];
    			
    			//insert type
    			if(property.equalsIgnoreCase("type"))
    			{
    				MasterPLOperations mp = new MasterPLOperations(username,password);
    				mp.setMaster(value);
    				mp.setNewProperty(value, "type", "property", "1");
    				mp.insertMaster(value);
    			}
    			
    			//insert "tag"/property
    			MasterPLOperations mp = new MasterPLOperations(username,password);
				mp.setMaster(property);
				mp.setNewProperty(property, "type", "property", "1");
				mp.insertMaster(property);
    			
    			masterpl.setMaster(start_object);
    			
    			if(new_hash.containsKey(value))
    			{
    				//masterpl.insertMaster(value);
    				GenerateMasterCommand gen = new GenerateMasterCommand(value,new_hash);
    				gen.setUsername(username);
    				gen.setPassword(password);
    				gen.register();
    			}
    			
    			masterpl.setNewProperty(start_object, property, value, ref);    			
	    	}
			
			masterpl.insertMaster(start_object);    		
		}
		catch(Exception e)
		{
			e.printStackTrace();
	    }
	}
    
    public void update()
    {
    	this.report = HtmlParseMain.report;
    	String file = Input.WEB_REPORTS_FILES+report+Input.FILRFORMAT;		
		FileObjectsfinder find = new FileObjectsfinder(file);
		old_hash = find.getObjectProperties();
		
		this.masterpl = new MasterPLOperations(username,password);
		
		System.out.println(old_hash);
		System.out.println(new_hash);		
		
		LinkedHashMap<Object, LinkedList<Object>>  old_object_hash = new LinkedHashMap<Object, LinkedList<Object>>();
		LinkedHashMap<Object, LinkedList<Object>>  new_object_hash = new LinkedHashMap<Object, LinkedList<Object>>();
		
		old_object_hash.put(report, old_hash.get(report));
		new_object_hash.put(HTMLParseLister.start_tag, new_hash.get(HTMLParseLister.start_tag));
						
		if(isPropertyEqual(report, HTMLParseLister.start_tag,"type"))
		{
			this.compareHash(old_object_hash, new_object_hash);
		}
	}
    
    private boolean compareHash(LinkedHashMap<Object, LinkedList<Object>> old_obj_hash, LinkedHashMap<Object, LinkedList<Object>> new_obj_hash)
    {
    	System.out.println(old_obj_hash);
		System.out.println(new_obj_hash);
		
		Iterator new_iterator = new_obj_hash.keySet().iterator();
		Iterator old_iterator = old_obj_hash.keySet().iterator();
		
		boolean emptyOldProperty = false, moreNewProperty = true;
		
    	try
		{
    		int counter = 0;
    		
    		while (old_iterator.hasNext() && new_iterator.hasNext())
    		{
				counter++;
				String old_element = (String) old_iterator.next();			
				String new_element = (String) new_iterator.next();
				
				// if the type of both objects is equal
				if(isPropertyEqual(old_element, new_element,"type"))
				{
        			LinkedList<Object> new_list = new_hash.get(new_element);        			
    				LinkedList<Object> old_list = old_hash.get(old_element);
    				
					for(int i=0;i< new_list.size()||i<old_list.size();i++)
					{
						String old_property=null, old_value=null, old_ref=null,new_property=null, new_value=null, new_ref=null;
						try
						{
							String new_arr[] = new_list.get(i).toString().split("\t");    						
							new_property = new_arr[0];
							new_value = new_arr[1];
							new_ref = new_arr[2];
						}
						catch (ArrayIndexOutOfBoundsException e) 
						{
							moreNewProperty = false;
						}
						
						try
						{
    						String old_arr[] = old_list.get(i).toString().split("\t");    						
    						old_property = old_arr[0];
    						old_value = old_arr[1];
    						old_ref = old_arr[2];
						}
						catch (ArrayIndexOutOfBoundsException e)
						{
							emptyOldProperty = true;
						}
						
						if(!emptyOldProperty && moreNewProperty)
						{
    						if(NonSequentialObjects.contains(new_property) && new_property.equalsIgnoreCase(old_property))
    						{
								if(!isPropertyEqual(old_element, new_element, new_property))
								{
									masterpl.setOldUpdateProperty(old_element, new_property, old_value ,old_ref);
									masterpl.setUpdateProperty(old_element,new_property,new_value,new_ref);
									masterpl.updateProperty();
								}	    						
    						}
    						else
    						{
    							if(new_property.equalsIgnoreCase(old_property))
    							{
    								// create two hashtables using new and old properties to compare
    								LinkedHashMap<Object, LinkedList<Object>> new_property_hash = new LinkedHashMap<Object, LinkedList<Object>>();
    								LinkedHashMap<Object, LinkedList<Object>> old_property_hash = new LinkedHashMap<Object, LinkedList<Object>>();
    								new_property_hash.put(new_value, new_hash.get(new_value));
    								old_property_hash.put(old_value, old_hash.get(old_value));
    								
    								/*if(!compareHash(old_property_hash, new_property_hash))
	    							{
    									//change property value
	    								//this.updateProperty(old_element,new_property,old_value,new_value,old_ref,new_ref);
	    							}*/
    								old_parent = old_element;
    								new_parent = new_element;
    								property = new_property;
    								ref = new_ref;
    								
    								if(new_property_hash!=null && old_property_hash!=null)
    									compareHash(old_property_hash, new_property_hash);
    							}
    							else
    							{
    								// replace with new object
    								masterpl.setremoveProperty(old_element, old_property, old_value, old_ref);
    								masterpl.removeProperty();
    								masterpl.setNewProperty(old_element, new_property, new_value, new_ref);
    								masterpl.insertProperty();
    							}
    						}
						}
						else if(emptyOldProperty)
						{
							masterpl.setNewProperty(old_element, new_property, new_value, new_ref);
							masterpl.insertProperty();
						}
						else if(!moreNewProperty)
						{
							masterpl.setremoveProperty(old_element, old_property, old_value, old_ref);
							masterpl.removeProperty();
						}
					}
				}
				else // if both objects are diff
				{
					masterpl.setremoveProperty(old_parent, property, old_element, ref);
					masterpl.removeProperty();
					masterpl.setNewProperty(old_parent, property, new_element, ref);
					masterpl.insertProperty();
					break;
				}
			}
		}
		catch (Exception e) 
		{
			e.printStackTrace();
		}
		
		return false;
    }
    
    /*
     * This method only compares basic properties like type, text, path using their values. 
     */
    private boolean isPropertyEqual(String old_object, String new_object, String property)
    {
    	String old_type="", new_type="";
    	boolean result = false;
		LinkedList<Object> old_list = old_hash.get(old_object);
		LinkedList<Object> new_list = new_hash.get(new_object);
		
		for(int i=0;i<old_list.size();i++)
		{
			if(old_list.get(i).toString().split("\t")[0].equalsIgnoreCase(property))
			{
				old_type = old_list.get(i).toString().split("\t")[1];
				break;
			}
		}
		
		for(int i=0;i<new_list.size();i++)
		{
			if(new_list.get(i).toString().split("\t")[0].equalsIgnoreCase(property))
			{
				new_type = new_list.get(i).toString().split("\t")[1];
				break;
			}
		}
    	
		if(old_type.equalsIgnoreCase(new_type))
		{
			result = true;
		}
		else
		{
			result = false;
		}
		
    	return result;
    }
}
       